﻿using System;
using System.Collections.Generic;
using System.Text;
using ITAP.ShprossesBuilder.Modelling.Components.Constraints;
using ITAP.Core.Modelling.Primitives;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using ITAP.ShprossesBuilder.Calculations;
using System.Drawing;
using System.Runtime.Serialization;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Modelling.Components
{
    public enum SpacerConnectorType
    {
        Internal,
        External
    }   

    [Serializable]
    public class SpacerConnector : Connector
    {
        private double indent;

        public double Indent
        {
            get { return indent; }
            set { indent = value; }
        }

        public double CurrentShprossIndent
        {
            get
            {
                return this.indent / Math.Sin(this.StartCutAngle.Value);
            }
        }        

        private bool inaccessibleFromMaterials = false;

        public override bool InaccessibleFromMaterials
        {
            get { return inaccessibleFromMaterials; }
            set { inaccessibleFromMaterials = value; }
        }

       public override List<IComponent> ConnectedComponents
        {
            get
            {
                return base.ConnectedComponents;
            }
        }

        SpacerConnectorType spacerConnectorType;

        public SpacerConnectorType SpacerConnectorType
        {
            get { return spacerConnectorType; }
            set { spacerConnectorType = value; }
        }        

        //protected bool selected = false;

        //public override bool Selected
        //{
        //    get
        //    {
        //        return selected;
        //    }
        //    set
        //    {
        //        selected = value;
        //    }
        //}

        public override ModelPoint Position
        {
            get
            {
                return (ModelPoint)this.StartPoint.Clone();
            }
        }

        private bool autoConnectComponentsInTolerance = true;

        public bool AutoConnectComponentsInTolerance
        {
            get { return autoConnectComponentsInTolerance; }
            set { autoConnectComponentsInTolerance = value; }
        }

        public override ModelPoint StartPoint
        {
            get
            {
                return base.StartPoint;
            }
            set
            {
                base.StartPoint = value;
            }
        }

        public override ModelPoint EndPoint
        {
            get
            {
                return base.EndPoint;
            }
            set
            {
                base.EndPoint = value;
            }
        }
        

        public override IComponent EndConnectedComponent
        {
            get
            {
                return base.EndConnectedComponent;
            }
            set
            {
                base.EndConnectedComponent = value;
            }
        }

        //public event ComponentConstraintEventDelegate BeforeFixingConstraint;

        //public event ComponentConstraintEventDelegate AfterFixingConstraint;

        public override bool IsUpdateRequired
        {
            get
            {
                return base.IsUpdateRequired;
            }
            set
            {
                base.IsUpdateRequired = value;
            }
        }

        public override void AcceptVisitor(IModelVisitor visitor)
        {
            visitor.Visit(this);
        }

        public override void Update()
        {
            base.Update();
        }

        public override IComponent ConnectTo(IComponent component)
        {
            return base.ConnectTo(component);
        }

        public override IComponent ConnectTo(IComponent component, ITAP.Core.Modelling.Primitives.EndType endForConnect)
        {
            return base.ConnectTo(component, endForConnect);
        }

        public override IComponent ConnectToEnded(IEndedComponent endedComponent, ITAP.Core.Modelling.Primitives.EndType endToConnect)
        {
            return base.ConnectToEnded(endedComponent, endToConnect);
        }

        public override IComponent DisconnectFrom(IComponent component)
        {
            return base.DisconnectFrom(component);
        }

        public override object Clone()
        {

            SpacerConnector clone = ComponentFactory.CreateSpacerConnector(this.Width, this.Length, this.Indent, this.StartPoint, this.Primitives[0].GetTangent(0), this.spacerConnectorType, this.article, this.color, this.borderColor, this.UniqueId, this.AcceptedUniqueIdsToConnect.ToArray());
            clone.inaccessibleFromMaterials = this.inaccessibleFromMaterials;
    
            return clone;

            //Stream stream = new MemoryStream();
            //BinaryFormatter binary = new BinaryFormatter();
            //binary.Serialize(stream, this);
            //stream.Seek(0, SeekOrigin.Begin);
            //SpacerConnector spacerConnector = (SpacerConnector)binary.Deserialize(stream);
            //stream.Close();
            //return spacerConnector;

        }

        public override bool MoveTo(ModelPoint destination)
        {
            ModelVector offset = new ModelVector(destination.X - this.StartPoint.X, destination.Y - this.StartPoint.Y);
            foreach (IPrimitive primitive in this.primitives)
                primitive.MoveWithOffset(offset);
            foreach (IComponent innerComponent in this.InnerComponents)
                innerComponent.MoveWithOffset(offset);
            return true;
        }

        public override void MoveStartPointTo(ModelPoint destination)
        {
            throw new NotImplementedException();
            //base.MoveStartPointTo(destination);
            //ModelVector offset = new ModelVector(destination.X - this.StartPoint.X, destination.Y - this.StartPoint.Y);

        }

        public override void MoveEndPointTo(ModelPoint destination)
        {
            throw new NotImplementedException();
//            base.MoveEndPointTo(destination);
        }

        public override bool MoveWithOffset(ModelVector offset)
        {
            foreach (IPrimitive primitive in this.primitives)
                primitive.MoveWithOffset(offset);

            foreach (IComponent innerComponent in this.InnerComponents)
                innerComponent.MoveWithOffset(offset);

            return true;
        }

        #region ICoveredByCap Members
        
        //public SnapOnCap SnapOnCap
        //{            
        //    get 
        //    {
        //        foreach (IComponent innerComponent in this.InnerComponents)
        //            if (innerComponent is SnapOnCap)
        //                return (SnapOnCap)innerComponent;

        //        return null;

        //    }
        //}

        #endregion

        private SpacerElement connectedSpacerElement;

        public SpacerElement ConnectedSpacerElement
        {
            get { return connectedSpacerElement; }
            set { connectedSpacerElement = value; }
        }

        public virtual SpacerConnector CloneWithoutConnections()
        {
            SpacerConnector clone = ComponentFactory.CreateSpacerConnector(this.Width, this.Length, this.Indent, this.StartPoint, new ModelVector(this.StartPoint, this.EndPoint), this.spacerConnectorType, this.article + " Clone", this.color, this.borderColor, this.UniqueId, this.AcceptedUniqueIdsToConnect.ToArray());
            return clone;
        }
    }
}
